﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using XRpgLibrary.SpriteClasses;
using EyesOfTheDragon.Events;
using XRpgLibrary.Events;
using Anthem.Components;
using Anthem.GameScreens;
using XRpgLibrary;
using EyesOfTheDragon.Attacks;
using EyesOfTheDragon.Globals;
namespace EyesOfTheDragon.Components
{
    public class MonsterSprite : IUpdate, IDraw, IDestroy, IPauseable
    {
        private bool _enabled = true;
        protected float _attackElapsed = 0;
        public bool Enabled
        {
            get { return _enabled; }
            set { _enabled = value; }
        }
        public virtual void destroy()
        {
            UpdateList.Instance.remove(this);
            DrawList.Instance.remove(this);
        }
       
        public virtual void Update(GameTime gameTime)
        {
            
        }
        public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
        }
        public virtual Rectangle getRect
        {
            get 
            { 
                return new Rectangle(); 
            }
        }
        public virtual void Kill()
        {
            EventRouter.Instance.update(MonsterGenerator.Monster_Killed);
            DestroyList.Instance.add(this);
            
            Enabled = false;
        }
    }
    public class BaseMonster: MonsterSprite
    {
        public AnimatedSprite animSprite;
        public PauseManager.PauseType OurMonsterType = PauseManager.PauseType.Ballerina;
        public override void Kill()
        {
            base.Kill();
            DeathAnimation da = new DeathAnimation(GamePlayScreen.Instance.GameRef);
            if (OurMonsterType == PauseManager.PauseType.Child)
                da.isBaby = true;
            da.init();
            da.Position = animSprite.position;
            
        }
        float searchElapsed = 2.5f;
        Random _rand = new Random();
        public BaseMonster(AnimatedSprite sp)
        {
            animSprite = sp;
        }
        public void init()
        {
            UpdateList.Instance.add(this);
            DrawList.Instance.add(animSprite);
          //  animSprite.Scale *= .5f;
            PhysicsSimulation.Instance.add(this.animSprite);
            Enabled = true;
        }
        public override void Update(GameTime gameTime)
        {
            float seconds = gameTime.ElapsedGameTime.Milliseconds / 1000f;
            searchElapsed += seconds;
            _attackElapsed -= seconds;

            bool left = false;
            if (Player.Instance.Sprite.Position.X < animSprite.position.X)
                left = true;

            if (_attackElapsed > 0)
                animSprite.Velocity = Vector2.Zero;
            if (searchElapsed >2)
            {
                animSprite.Velocity = (Player.Instance.Sprite.position - animSprite.Position) * .33f;
                if (animSprite.Velocity.Length() <= 100)
                {
                    Vector2 vel = animSprite.Velocity;
                    Vector2.Normalize(ref vel, out vel);
                    animSprite.Velocity = vel;
                    animSprite.Velocity *= 100;
                }
            }
            float dist = Vector2.Distance(Player.Instance.Sprite.position, animSprite.position);
            if (dist < 20)
            {
                if (Player.Instance.Vulnerable)
                {
                    if (Player.Instance.Sprite.getRect().Intersects(animSprite.getRect()))
                    {
                        if (_attackElapsed < 0)
                        {
                            _attackElapsed = 1f;
                            Player.Instance.Health -= 15;
                            if (Player.Instance.Health < 0)
                            {
                              //  GamePlayScreen.Instance.KillPlayer();
                            }
                           
                            SoundEffect soundFromFile = GamePlayScreen.Instance.GameRef.Content.Load<SoundEffect>(@"Sound\Monster");
                            soundFromFile.Play();
                            if (left)
                            {
                                
                                animSprite.CurrentAnimation = AnimationKey.AttackLeft;
                                animSprite.Position -= new Vector2(animSprite.Width * animSprite.Scale.X *.5f, 0);
                            }
                            else
                                animSprite.CurrentAnimation = AnimationKey.AttackRight;

                            if (_rand.Next(0, 9) > 6)
                            {
                                PauseManager.Instance.InitiateThreeSecondPause(OurMonsterType);
                            }
                        }
                    }
                }
            }
            animSprite.Update(gameTime);
            if (_attackElapsed > 0)
                return;
            else if (animSprite.CurrentAnimation == AnimationKey.AttackLeft)
            {
                animSprite.Position += new Vector2(animSprite.Width * animSprite.Scale.X * .5f, 0);
            }
            

            if (left)
                animSprite.CurrentAnimation = AnimationKey.Left;
            else
                animSprite.CurrentAnimation = AnimationKey.Right;
                if (animSprite.Velocity != Vector2.Zero)
                    animSprite.IsAnimating = true;
                else
                    animSprite.IsAnimating = false;
            
        }
        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
           // animSprite.Draw(gameTime, spriteBatch);
        }
        public override Rectangle getRect
        {
            get { return new Rectangle((int)animSprite.Position.X,(int) animSprite.Position.Y, animSprite.Width/2, animSprite.Height/2); }
        }
        public override void destroy()
        {
            bool removed = UpdateList.Instance.remove(this);
            if (!removed)
            {
                UpdateList.Instance.remove(this);
            }
            DrawList.Instance.remove(animSprite);
            PhysicsSimulation.Instance.remove(animSprite);
            Monster.Instance.removeMonster(this);

        }
    }

    public class FinalBoss : MonsterSprite, AIStateManager.IaiStateOwner
    {
        public AnimatedSprite animSprite;
        public Random Rand;
        public bool Vulnerable = true;
        private float _currentStateElapsed = 0;
        public float CurrentStateElapsed
        {
            get { return _currentStateElapsed; }
            set { _currentStateElapsed = value; }
        }
        public const short StunnedStateKey = 1;
        public const short AttackingStateKey = 2;
        public const short IdleStateKey = 3;
        public const short DissapearStateKey = 4;
        public const short DamageStateKey = 5;
        public int Health = 100;
        public int MaxHealth = 100;
        public bool FaceLeft
        {
            get
            {
                bool left = true;
                if (Player.Instance.Sprite.position.X > animSprite.position.X)
                    left = false;
                return left;
            }
        }
        public override void Kill()
        {
            base.Kill();

            
        }
        
        public void Damage(int Amount, bool Bat)
        {
            Health -= Amount;
            if (Bat)
                MaxHealth -= Amount;
            
        }
        public FinalBoss(AnimatedSprite sp)
        {
            animSprite = sp;
        }
        public static FinalBoss Instance;
        public void init()
        {
            Instance = this;
            UpdateList.Instance.add(this);
            DrawList.Instance.add(animSprite);
           // animSprite.Scale *= .5f;
            PhysicsSimulation.Instance.add(this.animSprite);
            Enabled = true;
            _aiMangager = new AIStateManager();
            _aiMangager.addState(new AttackingState());
            _aiMangager.addState(new DissapearState());
            _aiMangager.addState(new StunnedState());
            _aiMangager.addState(new DamageState());
            _aiMangager.CurrentState = new IdleState();
            _aiMangager.addState(_aiMangager.CurrentState);
            Rand = new Random();
        }
        public override void Update(GameTime gameTime)
        {
            if (Health < 0)
            {
                Enabled = false;
                Instance = null;
                GamePlayScreen.Instance.WinGame();
            }
            _aiMangager.Update(gameTime, this);
            _aiMangager.Execute(this);
            animSprite.Update(gameTime);
        }
        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
           // animSprite.Draw(gameTime, spriteBatch);
        }
        public override Rectangle getRect
        {
            get { return new Rectangle((int)animSprite.Position.X,(int) animSprite.Position.Y, animSprite.Width/2, animSprite.Height/2); }
        }
        public override void destroy()
        {
            bool removed = UpdateList.Instance.remove(this);
            if (!removed)
            {
                UpdateList.Instance.remove(this);
            }
            DrawList.Instance.remove(animSprite);
            PhysicsSimulation.Instance.remove(animSprite);
            Monster.Instance.removeMonster(this);

        }
        protected class StunnedState : AIStateManager.AIState
        {
            public StunnedState()
            {
                key = 1;
            }
            private const float damageTime = 1.5f;

            public override void Update(GameTime gt, AIStateManager.IaiStateOwner owner)
            {
                base.Update(gt, owner);
            }
            public override short Execute(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                if (fb.CurrentStateElapsed > damageTime)
                    return FinalBoss.IdleStateKey;
                return 0;
            }
            public override void Enter(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                fb.Vulnerable = false;
                if (fb.FaceLeft)
                    fb.animSprite.CurrentAnimation = AnimationKey.DamageLeft;
                else
                    fb.animSprite.CurrentAnimation = AnimationKey.DamageRight;
                base.Enter(owner);
            }
            public override void Exit(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                fb.Vulnerable = true;
                base.Exit(owner);
            }
        }
        protected class AttackingState : AIStateManager.AIState
        {
            public AttackingState() 
            {
                key = 2;
            }
            private const float attackTime = .75f;

            public override void Update(GameTime gt, AIStateManager.IaiStateOwner owner)
            {
                base.Update(gt, owner);
            }
            public override short Execute(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                if (fb.CurrentStateElapsed > attackTime)
                {
                    return FinalBoss.IdleStateKey;
                }
                return 0;
            }
            public override void Enter(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                if (fb.FaceLeft)
                    fb.animSprite.CurrentAnimation = AnimationKey.AttackLeft;
                else
                    fb.animSprite.CurrentAnimation = AnimationKey.AttackRight;
                fb.animSprite.animations[fb.animSprite.CurrentAnimation].CurrentFrame = 0;
                if (Vector2.Distance(Player.Instance.Sprite.position, fb.animSprite.position) < 100)
                {
                    BossExplosion ba = new BossExplosion(GamePlayScreen.Instance.GameRef);
                    ba.Position = (fb.animSprite.position + Player.Instance.Sprite.position) / 2;
                    
                    ba.init();
                }
                else
                {
                    bool left = false;
                    if (Player.Instance.getRect().Center.X < fb.animSprite.getRect().Center.X)
                        left = true;
                    Vector2 vec1 = new Vector2(4, 3);
                    Vector2 vec2 = new Vector2(4, -3);
                    Vector2 vec3 = new Vector2(4, 0);
                    createBossAttack(vec1, left, fb);
                    createBossAttack(vec2, left, fb);
                    createBossAttack(vec3, left, fb);
                }
                base.Enter(owner);
            }
            protected void createBossAttack(Vector2 vec, bool left, FinalBoss fb)
            {
                BossAttack ba = new BossAttack(GamePlayScreen.Instance.GameRef);
                ba.Position = fb.animSprite.position;//+ Player.Instance.Sprite.position)/2;
                Vector2 vel = vec;
                Vector2.Normalize(ref vel, out vel);
                //  = ba.Velocity.Normalize(
                vel *= 150;
                ba.Velocity = vel;
                if (left)
                    ba.Velocity *= new Vector2(-1, 1);
                ba.init();
            }
            public override void Exit(object owner)
            {
                FinalBoss fb = owner as FinalBoss;

                base.Exit(owner);
            }
        }
        protected class IdleState : AIStateManager.AIState
        {
            public IdleState()
            {
                key = 3;
            }
            private static float idleTime = .75f;

            public override void Update(GameTime gt, AIStateManager.IaiStateOwner owner)
            {
                base.Update(gt, owner);
            }
            public override short Execute(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                if (fb.CurrentStateElapsed > idleTime)
                {
                    idleTime = fb.Rand.Next(75, 200) / 100f;
                    int ran = fb.Rand.Next(0,125);
                    if (ran + fb.Health > 100)
                        return FinalBoss.AttackingStateKey;
                    else
                        return FinalBoss.DissapearStateKey;
                }
                return 0;
            }
            public override void Enter(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                if (fb.FaceLeft)
                    fb.animSprite.CurrentAnimation = AnimationKey.Left;
                else
                    fb.animSprite.CurrentAnimation = AnimationKey.Right;
                base.Enter(owner);
            }
            public override void Exit(object owner)
            {
                FinalBoss fb = owner as FinalBoss;

                base.Exit(owner);
            }
        }
        protected class DissapearState: AIStateManager.AIState
        {
            private const int SpawnTriggerGID = 201;
            private const string triggerLayer = "triggersLayer";
            private const float dissapearTime = 2;
            public DissapearState()
            {
                key = 4;
            }
            public override void Update(GameTime gt, AIStateManager.IaiStateOwner owner)
            {
                base.Update(gt, owner);
            }
            public override short Execute(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                if (fb.CurrentStateElapsed > dissapearTime)
                    return FinalBoss.IdleStateKey;
                return 0;
            }
            public override void Enter(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                fb.animSprite.Visible = false;
                fb.Vulnerable = false;
                fb.Health += 10;
                if (fb.Health > fb.MaxHealth)
                    fb.Health = fb.MaxHealth;
                base.Enter(owner);
            }
            public override void Exit(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                fb.animSprite.Visible = true;
                fb.Vulnerable = true;
                List<GTile> tiles = map.Instance.getLayer(triggerLayer).getTiles(MapVariables.SpawnGID);
                int ran = fb.Rand.Next(0, tiles.Count - 1);
                fb.animSprite.Position = new Vector2(tiles[ran].Position.X, tiles[ran].Position.Y - fb.animSprite.Height/2);
                base.Exit(owner);
            }
        }
        protected class DamageState : AIStateManager.AIState
        {
            public DamageState()
            {
                key = 5;
            }
            private const float damageTime = .75f;

            public override void Update(GameTime gt, AIStateManager.IaiStateOwner owner)
            {
                base.Update(gt, owner);
            }
            public override short Execute(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                if (fb.CurrentStateElapsed > damageTime)
                    return FinalBoss.IdleStateKey;
                return 0;
            }
            public override void Enter(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                fb.Vulnerable = false;
                if (fb.FaceLeft)
                    fb.animSprite.CurrentAnimation = AnimationKey.DamageLeft;
                else
                    fb.animSprite.CurrentAnimation = AnimationKey.DamageRight;
                base.Enter(owner);
            }
            public override void Exit(object owner)
            {
                FinalBoss fb = owner as FinalBoss;
                fb.Vulnerable = true;
                base.Exit(owner);
            }
        }

        private AIStateManager _aiMangager;
    }

}
